package exercice_2;

import java.awt.Color;
import java.awt.Graphics;

public class LkSol extends Lk{

    private static final long serialVersionUID = 1L;
    private double a;
    private double b;
    
    /**
     * Constructeur qui appelle le super constructeur
     * 
     * @param prof
     *       Nombre d'itérations
     */
    public LkSol(int prof) {
        super(prof);
    }

    /**
     * Méthode drawLk - Produit un dessin recursif de Lk
     *
     * @param k
     *       Nombre d'itérations
     * @param x
     *       Abscisse du point de départ
     * @param y 
     *       L'ordonnée du point de départ
     * @param longueur
     *       Longueur voulue
     * @param drawingArea
     *       L'objet graphique dans lequel Ck est dessiné
     **/
    @Override
    public void drawLk(int x, int y, int longueur, int k, Graphics drawingArea) {
        a = x;
        b = y;
        drawHilbertH(k, longueur/(3*k), drawingArea); // Ici longueur/(3*k) pour une meilleure vision de la figure
    }

    /**
     * Méthode alteredDrawing - Dessine un trait 
     * @param k 
     *       Niveau de récurrence
     * @param dx
     *       
     * @param dy 
     *       
     * @param longueurCarre
     *       Longueur d'un côté du carré
     * @param drawingArea
     *       L'objet graphique dans lequel Ck est dessiné
     */
    public void alteredDrawing(double dx, double dy, double longueurCarre, int k,
            Graphics drawingArea) {
        double ancienA = a;
        double ancienB = b;
        a = a + longueurCarre * dx;
        b = b + longueurCarre * dy;
        drawingArea.drawLine((int)ancienA, (int)ancienB, (int)a, (int)b);

    }

    /**
     * Méthode drawHilbertH - Dessine la 1ère itération haute
     * @param cpt
     *       Niveau de récurrence
     * @param longueurCarre
     *       Longueur d'un côté du carré
     * @param drawingArea
     *       L'objet graphique dans lequel Ck est dessiné
     */
    public void drawHilbertH(int cpt, double longueurCarre, Graphics drawingArea) {
        drawingArea.setColor(Color.black);
        if(cpt>1){
            drawHilbertD(cpt-1,longueurCarre, drawingArea);
            drawHilbertH(cpt-1,longueurCarre, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(-1, 0, longueurCarre*Math.pow(2,(cpt-2)),cpt,  drawingArea);
            alteredDrawing(0, -1, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(0, 1, longueurCarre, cpt, drawingArea);
            alteredDrawing(0, -1, longueurCarre/2, cpt, drawingArea);
            drawingArea.setColor(Color.white);
            alteredDrawing(1, 0, longueurCarre/2, cpt, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(1, 0, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            alteredDrawing(-1, 0, longueurCarre/2, cpt, drawingArea);
            drawHilbertH(cpt-1,longueurCarre, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(-1, 0, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            drawingArea.setColor(Color.white);
            alteredDrawing(0, -1, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(0, 1, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(1, 0, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(0, -1, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(0, 1, longueurCarre/2, cpt, drawingArea);
            drawHilbertG(cpt-1,longueurCarre, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(0, -1, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            alteredDrawing(0, -1, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(0, 1, longueurCarre/2, cpt, drawingArea);
            drawingArea.setColor(Color.white);
            alteredDrawing(-1, 0, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(1, 0, longueurCarre/2, cpt, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(0, 1, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            if(cpt % 2 == 0){
                drawingArea.setColor(Color.white);
                alteredDrawing(0, -1, longueurCarre/2, cpt, drawingArea);
                alteredDrawing(0, 1, longueurCarre/2, cpt, drawingArea);
            }
            else{
                drawingArea.setColor(Color.white);
                alteredDrawing(-1, 0, longueurCarre/2, cpt, drawingArea);
                alteredDrawing(1, 0, longueurCarre/2, cpt, drawingArea);
            }

        }
        else{
            //Dessiner le hilbert haut
            //
            alteredDrawing(0, -1, longueurCarre, cpt, drawingArea);
            alteredDrawing(1, 0, longueurCarre, cpt, drawingArea);
            alteredDrawing(0, 1, longueurCarre, cpt, drawingArea);
            
            //Tracer la diagonal gauche pour se déplacer au centre du carré
            //
            drawingArea.setColor(Color.white);
            alteredDrawing(-1, -1, longueurCarre/2, cpt, drawingArea);
            
            drawingArea.setColor(Color.black);
            alteredDrawing(0, 1, longueurCarre/2, cpt, drawingArea);
            
            //Se déplacer à l'extrémité droite du carré
            //
            drawingArea.setColor(Color.white);
            alteredDrawing(1, 0, longueurCarre/2, cpt, drawingArea);
        }

    }

    /**
     * Méthode drawHilbertB - Dessine la 1ère itération basse
     * @param cpt
     *       Niveau de récurrence
     * @param longueurCarre
     *       Longueur d'un côté du carré
     * @param drawingArea
     *       L'objet graphique dans lequel Ck est dessiné
     */
    public void drawHilbertB(int cpt, double longueurCarre, Graphics drawingArea) {
        drawingArea.setColor(Color.black);
        if(cpt>1){
            drawHilbertG(cpt-1,longueurCarre, drawingArea);
            drawHilbertB(cpt-1,longueurCarre, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(1, 0, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            alteredDrawing(0, 1, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(0, -1, longueurCarre, cpt, drawingArea);
            alteredDrawing(0, 1, longueurCarre/2, cpt, drawingArea);
            drawingArea.setColor(Color.white);
            alteredDrawing(-1, 0, longueurCarre/2, cpt, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(-1, 0, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            alteredDrawing(1, 0, longueurCarre/2, cpt, drawingArea);
            drawHilbertB(cpt-1,longueurCarre, drawingArea);
            drawingArea.setColor(Color.white);
            alteredDrawing(1, 0, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            alteredDrawing(0, 1, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(0, -1, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(-1, 0, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            drawHilbertD(cpt-1,longueurCarre, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(0, 1, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            alteredDrawing(0, 1, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(0, -1, longueurCarre/2, cpt, drawingArea);
            drawingArea.setColor(Color.white);
            alteredDrawing(1, 0, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(-1, 0, longueurCarre/2, cpt, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(0, -1, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            if(cpt % 2 == 0){
                drawingArea.setColor(Color.white);
                alteredDrawing(0, 1, longueurCarre/2, cpt, drawingArea);
                alteredDrawing(0, -1, longueurCarre/2, cpt, drawingArea);
            }
        }
        else{
            // Dessiner le hilbert Bas
            //
            alteredDrawing(0, 1, longueurCarre, cpt, drawingArea);
            alteredDrawing(-1, 0, longueurCarre, cpt, drawingArea);
            alteredDrawing(0, -1, longueurCarre, cpt, drawingArea);
            
            // Se déplacer au centre du carré
            //
            drawingArea.setColor(Color.white);
            alteredDrawing(1, 1, longueurCarre/2, cpt, drawingArea);
            
            // Tracer la dernière composante
            //
            drawingArea.setColor(Color.black);
            alteredDrawing(0, -1, longueurCarre/2, cpt, drawingArea);
            
            // Se replacer la l'extrémité
            //
            drawingArea.setColor(Color.white);
            alteredDrawing(-1, 0, longueurCarre/2, cpt, drawingArea);
        }

    }

    /**
     * Méthode drawHilbertG - Dessine la 1ère itération gauche
     * @param cpt
     *       Niveau de récurrence
     * @param longueurCarre
     *       Longueur d'un côté du carré
     * @param drawingArea
     *       L'objet graphique dans lequel Ck est dessiné
     */
    public void drawHilbertG(int cpt, double longueurCarre, Graphics drawingArea) {
        drawingArea.setColor(Color.black);
        if(cpt>1){
            drawHilbertB(cpt-1,longueurCarre, drawingArea);
            drawHilbertG(cpt-1,longueurCarre, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(0, -1, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            alteredDrawing(-1, 0, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(1, 0, longueurCarre, cpt, drawingArea);
            alteredDrawing(-1, 0, longueurCarre/2, cpt, drawingArea);
            drawingArea.setColor(Color.white);
            alteredDrawing(0, 1, longueurCarre/2, cpt, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(0, 1, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            alteredDrawing(0, -1, longueurCarre/2, cpt, drawingArea);
            drawHilbertG(cpt-1,longueurCarre, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(0, -1, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            drawingArea.setColor(Color.white);
            alteredDrawing(-1, 0, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(1, 0, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(0, 1, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            drawHilbertH(cpt-1,longueurCarre, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(-1, 0, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            alteredDrawing(-1, 0, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(1, 0, longueurCarre/2, cpt, drawingArea);
            drawingArea.setColor(Color.white);
            alteredDrawing(0, -1, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(0, 1, longueurCarre/2, cpt, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(1, 0, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            if(cpt % 2 == 0){
                drawingArea.setColor(Color.white);
                alteredDrawing(-1, 0, longueurCarre/2, cpt, drawingArea);
                alteredDrawing(1, 0, longueurCarre/2, cpt, drawingArea);
            }
        }
        else{
            
            // Dessiner le hilbert Gauche
            //
            alteredDrawing(-1, 0, longueurCarre, cpt, drawingArea);
            alteredDrawing(0, 1, longueurCarre, cpt, drawingArea);
            alteredDrawing(1, 0, longueurCarre, cpt, drawingArea);
            
            drawingArea.setColor(Color.white);
            alteredDrawing(-1, -1, longueurCarre/2, cpt, drawingArea);
            
            // Tracer la dernière composante
            //
            drawingArea.setColor(Color.black);
            alteredDrawing(1, 0, longueurCarre/2, cpt, drawingArea);
            
            drawingArea.setColor(Color.white);
            alteredDrawing(0, 1, longueurCarre/2, cpt, drawingArea);
        }

    }

    /**
     * Méthode drawHilbertD - Dessine la 1ère itération droite
     * @param cpt
     *       Niveau de récurrence
     * @param longueurCarre
     *       Longueur d'un côté du carré
     * @param drawingArea
     *       L'objet graphique dans lequel Ck est dessiné
     */
    public void drawHilbertD(int cpt, double longueurCarre, Graphics drawingArea) {
        drawingArea.setColor(Color.black);
        if(cpt>1){
            drawHilbertH(cpt-1,longueurCarre,drawingArea);
            drawHilbertD(cpt-1,longueurCarre,drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(0, 1, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            alteredDrawing(1, 0, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(-1, 0, longueurCarre, cpt, drawingArea);
            alteredDrawing(1, 0, longueurCarre/2, cpt, drawingArea);
            drawingArea.setColor(Color.white);
            alteredDrawing(0, -1, longueurCarre/2, cpt, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(0, -1, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            alteredDrawing(0, 1, longueurCarre/2, cpt, drawingArea);
            drawHilbertD(cpt-1,longueurCarre, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(0, 1, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            drawingArea.setColor(Color.white);
            alteredDrawing(1, 0, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(-1, 0, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(0, -1, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            drawHilbertB(cpt-1,longueurCarre,drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(1, 0, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            alteredDrawing(1, 0, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(-1, 0, longueurCarre/2, cpt, drawingArea);
            drawingArea.setColor(Color.white);
            alteredDrawing(0, 1, longueurCarre/2, cpt, drawingArea);
            alteredDrawing(0, -1, longueurCarre/2, cpt, drawingArea);
            drawingArea.setColor(Color.black);
            alteredDrawing(-1, 0, longueurCarre*Math.pow(2,(cpt-2)), cpt, drawingArea);
            if(cpt % 2 == 0){
                drawingArea.setColor(Color.white);
                alteredDrawing(1, 0, longueurCarre/2, cpt, drawingArea);
                alteredDrawing(-1, 0, longueurCarre/2, cpt, drawingArea);
            }
        }
        else{
            // Dessiner le hilbert Droite
            //
            alteredDrawing(1, 0, longueurCarre, cpt, drawingArea);
            alteredDrawing(0, -1, longueurCarre, cpt, drawingArea);
            alteredDrawing(-1, 0, longueurCarre, cpt, drawingArea);
            
            // Se deplacer au centre du carré
            //
            drawingArea.setColor(Color.white);
            alteredDrawing(1, 1, longueurCarre/2, cpt, drawingArea);
            
            // Tracer la dernière composante
            //
            drawingArea.setColor(Color.black);
            alteredDrawing(-1, 0, longueurCarre/2, cpt, drawingArea);
            
            // Se replacer
            //
            drawingArea.setColor(Color.white);
            alteredDrawing(0, -1, longueurCarre/2, cpt, drawingArea);
        }
    }
}